package com.zhouyu.exampledesignmoudle.util;


import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
import org.springframework.util.StringUtils;

/**
 * @author 周宇
 * @version 1.0 date: 2019/7/25 15:10
 * @description: 时间工具类
 * @Copyright (C), 2017-2019, 深圳市⾦证引擎科技股份有限公司
 */
public class TimeUtil {

  public static final ZoneId chinaZone = ZoneId.systemDefault();
  public static final String YYYY_MMDD_HHMMSS = "yyyyMMddHHmmss";
  public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

  /**
   * 获取当天日期
   *
   * @return LocalDate
   */
  public static LocalDate nowDate() {
    return LocalDate.now();
  }

  /**
   * 获取当前时间
   * @return Timestamp
   * @author  zhangyao
   * date: 2018/8/22 11:36
   */
  public static Timestamp now() {
    return new Timestamp(Calendar.getInstance().getTimeInMillis());
  }

  /**
   * 将日期转换为格式为yyyy-MM-dd HH:mm:ss的日期字符串
   * @param date 日期
   * @return String
   * @author  zhangyao
   * date: 2018/8/24 13:46
   */
  public static String formatDateyyyyMMddHHmmss(Date date) {
    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
  }

  /**
   * 获取现在时间
   *
   * @return yyyy-MM-dd HH:mm:ss日期
   */
  public static String nowTimeStr1() {
    return LocalDateTime.now().format(DateTimeFormatter.ofPattern(YYYY_MMDD_HHMMSS));
  }

  /**
   * 获取现在时间
   *
   * @return yyyyMMddHHmmss 日期
   */
  public static String nowTimeStr2() {
    return LocalDateTime.now().format(DateTimeFormatter.ofPattern(YYYY_MMDD_HHMMSS));
  }

  /**
   * 获取当地日期
   */
  public static LocalDateTime dateToLocalDateTime(Date date) {
    return LocalDateTime.ofInstant(date.toInstant(), chinaZone);
  }

  /**
   * 日期时间对象转换为日期对象
   *
   * @param localDateTime 日期时间对象
   * @return 日期对象
   */
  public static LocalDate dateTime2Date(LocalDateTime localDateTime) {
    return localDateTime.toLocalDate();

  }

  /**
   * 日期对象转换为日期对象
   *
   * @param localDate 日期对象
   * @return 日期时间对象
   */
  public static LocalDateTime date2DateTIme(LocalDate localDate) {
    return LocalDateTime.of(localDate, LocalTime.NOON);
  }

  /**
   * 字符串转换为日期
   *
   * @param strDate 字符串日期
   * @return 日期对象 yyyy-mm-dd
   */
  public static LocalDate str2LocalDate(String strDate) {
    return LocalDate.parse(strDate, DateTimeFormatter.ISO_DATE);
  }

  /**
   * 字符串转换为日期
   *
   * @param strDate 字符串日期
   * @return 日期对象 yyyy-mm-dd
   */
  public static LocalDateTime str2LocalDateTime(String strDate, DateTimeFormatter formatter) {
    return LocalDateTime.parse(strDate, formatter);
  }

  /**
   * yyyyMMddHHmmss时间转LocalDateTime
   */
  public static LocalDateTime str2LocalDateTime(String strDate) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YYYY_MMDD_HHMMSS);
    return LocalDateTime.parse(strDate, formatter);
  }

  /**
   * LocalDateTime转换为Date
   */
  public static Date localDateTime2Date(LocalDateTime localDateTime) {
    return Date.from(localDateTime.atZone(chinaZone).toInstant());
  }

  /**
   * LocalDateTime转换为Date
   */
  public static Date str2Date(String strDate, String formatter) {
    return localDateTime2Date(str2LocalDateTime(strDate, DateTimeFormatter.ofPattern(formatter)));
  }

  /**
   * yyyyMMddHHmmss时间转Date
   */
  public static Date str2dateWithYMDHMS(String yyyyMMddHHmmssTime) {
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern(YYYY_MMDD_HHMMSS);
    LocalDateTime ldt = LocalDateTime.parse(yyyyMMddHHmmssTime, dtf);
    return localDateTime2Date(ldt);
  }

  /**
   * 日期对象转换为字符串
   *
   * @param localDate 日期对象
   * @return 日期字符串 yyyy-mm-dd
   */
  public static String date2Str(LocalDate localDate) {
    return localDate.format(DateTimeFormatter.ISO_DATE);
  }

  /**
   * 日期时间对象转换为字符串
   *
   * @param localDateTime 日期时间对象
   * @param dateTimeFormatter 格式化字符串
   * @return 日期字符串
   */
  public static String dateTime2Str(LocalDateTime localDateTime, String dateTimeFormatter) {
    return localDateTime.format(DateTimeFormatter.ofPattern(dateTimeFormatter));
  }

  public static  String dateTime2StrYYYY_MM_DD_HH_MM_SS(LocalDateTime localDateTime){
    return localDateTime.format(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
  }

  /**
   * 日期时间转字符串函数 返回ISO标准的日期字符串
   *
   * @param localDateTime 日期时间对象
   * @return 日期字符串
   */
  public static String dateTime2Str(LocalDateTime localDateTime) {
    return localDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
  }

  /**
   * 获取东八时间戳,秒级
   */
  public static long getTimeStrampMiniseconds() {
    //获取秒数
    return LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
  }

  /**
   * 获取东八时间戳,毫秒级
   */
  public static long getTimeStrampSeconds() {
    //获取秒数
    return LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
  }

  /**
   * date 转string： yyyy-MM-dd HH:mm:ss
   */
  public static String fromDate2Str(Date date) {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    return simpleDateFormat.format(date);
  }

  /**
   * 计算两个时间之间相差的秒数
   *
   * @param date1 起始时间
   * @param date2 结束时间
   */
  public static long secondsBetween(LocalDateTime date1, LocalDateTime date2) {
    Duration duration = Duration.between(date1, date2);
    return duration.getSeconds();
  }

  /**
   * 计算两个日期之间相差的天数
   *
   * @param date1 起始日期
   * @param date2 结束日期
   */
  public static int daysBetween(LocalDate date1, LocalDate date2) {
    Period period = Period.between(date1, date2);
    return period.getDays();
  }

  /**
   * 计算两个日期之间相差的月数
   *
   * @param date1 起始日期
   * @param date2 结束日期
   */
  public static int monthsBetween(LocalDate date1, LocalDate date2) {
    Period period = Period.between(date1, date2);
    return period.getMonths();
  }

  /**
   * 计算两个日期之间相差的年数
   *
   * @param date1 起始日期
   * @param date2 结束日期
   */
  public static int yearsBetween(LocalDate date1, LocalDate date2) {
    Period period = Period.between(date1, date2);
    return period.getYears();
  }

  /**
   * 计算两个日期之间相差的天数
   *
   * @param date1 起始日期
   * @param date2 结束日期
   */
  public static int daysBetween(Date date1, Date date2) {
    Instant instantDate1 = date1.toInstant();
    Instant instantDate2 = date2.toInstant();
    LocalDate localDate1 = instantDate1.atZone(chinaZone).toLocalDate();
    LocalDate localDate2 = instantDate2.atZone(chinaZone).toLocalDate();
    instantDate1.atZone(chinaZone);
    Period period = Period.between(localDate1, localDate2);
    return period.getDays();
  }

  /**
   * 计算两个日期之间相差的月数
   *
   * @param date1 起始日期
   * @param date2 结束日期
   */
  public static int monthsBetween(Date date1, Date date2) {
    Instant instantDate1 = date1.toInstant();
    Instant instantDate2 = date2.toInstant();
    LocalDate localDate1 = instantDate1.atZone(chinaZone).toLocalDate();
    LocalDate localDate2 = instantDate2.atZone(chinaZone).toLocalDate();
    instantDate1.atZone(chinaZone);
    Period period = Period.between(localDate1, localDate2);
    return period.getMonths();
  }

  /**
   * 计算两个日期之间相差的年数
   *
   * @param date1 起始日期
   * @param date2 结束日期
   */
  public static int yearsBetween(Date date1, Date date2) {
    Instant instantDate1 = date1.toInstant();
    Instant instantDate2 = date2.toInstant();
    LocalDate localDate1 = instantDate1.atZone(chinaZone).toLocalDate();
    LocalDate localDate2 = instantDate2.atZone(chinaZone).toLocalDate();
    instantDate1.atZone(chinaZone);
    Period period = Period.between(localDate1, localDate2);
    return period.getYears();
  }

  /**
   * 获取指定日期对象当前月的起始日
   *
   * @param localDate 指定日期
   */
  public static int getFirstDayInMonth(LocalDate localDate) {
    LocalDate result = localDate.with(TemporalAdjusters.firstDayOfMonth());
    return result.getDayOfMonth();

  }

  /**
   * 获取指定日期对象的当前月的结束日
   *
   * @param localDate 指定日期
   */
  public static int getLastDayInMonth(LocalDate localDate) {
    LocalDate result = localDate.with(TemporalAdjusters.lastDayOfMonth());
    return result.getDayOfMonth();
  }

  /**
   * 获取指定日期对象本月的某周某天的日期
   *
   * @param localDate 日期对象
   * @param weekNumber 周
   * @param dayNumber 日
   */
  public static LocalDate getLocalDateBydayAndWeek(LocalDate localDate, int weekNumber,
      int dayNumber) {
    return localDate.with(TemporalAdjusters.dayOfWeekInMonth(weekNumber, DayOfWeek.of(dayNumber)));
  }

  /**
   * 获取小时
   */
  public static String getHour(LocalDateTime localDate) {
    return dateTime2Str(localDate, YYYY_MMDD_HHMMSS).substring(8, 10);
  }

  /**
   * 获取当天
   */
  public static String getDay(LocalDateTime localDate) {
    return dateTime2Str(localDate, YYYY_MMDD_HHMMSS).substring(6, 8);
  }

  /**
   * 获取后续日期
   *
   * @param d 当前日期
   * @param squence 完后多长时间
   * @return Date
   * @author zhangyao date: 2018/11/8 19:45
   */
  public static Date after(Date d, int squence) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(d);
    cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY) + squence
        * 24);
    return new Date(cal.getTimeInMillis());
  }

  /**
   * 获取两日期区间
   *
   * @param d1 日期
   * @param d2 日期
   * @return int
   * @author zhangyao date: 2018/11/9 14:04
   */
  public static int dayDistance(Date d1, Date d2) {
    if ((d1 == null) || (d2 == null)) {
      throw new IllegalAccessError("the date must be not null");
    }
    Calendar cal1 = Calendar.getInstance();
    cal1.setTime(d1);
    cal1.set(Calendar.HOUR_OF_DAY, 0);
    cal1.set(Calendar.MINUTE, 0);
    cal1.set(Calendar.SECOND, 0);
    cal1.set(Calendar.MILLISECOND, 0);

    Calendar cal2 = Calendar.getInstance();
    cal2.setTime(d2);
    cal2.set(Calendar.HOUR_OF_DAY, 0);
    cal2.set(Calendar.MINUTE, 0);
    cal2.set(Calendar.SECOND, 0);
    cal2.set(Calendar.MILLISECOND, 0);

    Long result = Math
        .abs((cal2.getTime().getTime() - cal1.getTime().getTime()) / (1000 * 60 * 60 * 24));
    return Integer.valueOf(result.toString()).intValue();
  }

  /**
   * 比较日期
   *
   * @param d1 Date
   * @param d2 Date
   * @return boolean
   * @author zhangyao date: 2018/11/9 17:40
   */
  public static boolean compare(Date d1, Date d2) {
    Calendar c1 = Calendar.getInstance();
    Calendar c2 = Calendar.getInstance();
    c1.setTime(d1);
    c2.setTime(d2);
    return c1.getTimeInMillis() > c2.getTimeInMillis();
  }


  /**
   * description 得到一天的开始时间
   *
   * @param d 某天时间
   * @return Timestamp 该天开始时间
   * @author YS date:   2018/11/13 0013 18:42 history:
   */
  public static Timestamp getDayStart(Date d) {
    Calendar c = Calendar.getInstance();
    c.setTime(d);
    c.set(Calendar.HOUR_OF_DAY, 0);
    c.set(Calendar.MINUTE, 0);
    c.set(Calendar.SECOND, 0);
    // c.set(Calendar.MILLISECOND, 0);
    return new Timestamp(c.getTimeInMillis());
  }

  /**
   * description 得到一天的结束时间
   *
   * @param d 某天时间
   * @return Timestamp 该天结束时间
   * @author YS date:   2018/11/13 0013 18:42 history:
   */
  public static Timestamp getDayEnd(Date d) {
    Calendar c = Calendar.getInstance();
    c.setTime(d);
    c.set(Calendar.HOUR_OF_DAY, 23);
    c.set(Calendar.MINUTE, 59);
    c.set(Calendar.SECOND, 59);
    // c.set(Calendar.MILLISECOND, 0);
    return new Timestamp(c.getTimeInMillis());

  }


  /**
   * 日期格式化
   *
   * @param date 日期
   * @param pattern 格式
   * @return String
   * @author xiaozhiwei date: 2019/1/2 16:54
   */
  public static String formatDate(Date date, String pattern) {
    SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
    return dateFormat.format(date);
  }


  /**
   * description 判断是否为同一天
   *
   * @param date1 第一个时间参数
   * @param date2 第二个时间参数
   * @return boolean
   * @author YS date:   2018/11/13 0013 18:42 history:
   */
  public static boolean isSameDay(Date date1, Date date2) {
    if ((date1 == null) || (date2 == null)) {
      throw new IllegalArgumentException("The date must not be null");
    }
    Calendar cal1 = Calendar.getInstance();
    cal1.setTime(date1);
    Calendar cal2 = Calendar.getInstance();
    cal2.setTime(date2);
    return isSameDay(cal1, cal2);
  }


  /**
   * description根据cal1判断是否为同一天
   *
   * @param cal1 时间
   * @param cal2 时间
   * @return boolean
   * @author YS date:   2018/11/13 0013 18:42 history:
   */
  public static boolean isSameDay(Calendar cal1, Calendar cal2) {
    if ((cal1 == null) || (cal2 == null)) {
      throw new IllegalArgumentException("The date must not be null");
    }
    return ((cal1.get(0) == cal2.get(0)) && (cal1.get(1) == cal2.get(1)) && (cal1
        .get(6) == cal2.get(6)));
  }


  /**
   * @param s String
   * @return Timestamp
   */
  public static Timestamp parseTime(String s) throws ParseException {
    if (!StringUtils.isEmpty(s)) {
      if (s.length() == 10) {
        s += " 00:00:00";
      }
      SimpleDateFormat format = new SimpleDateFormat(
          "yyyy-MM-dd HH:mm:ss");
      return new Timestamp(format.parse(s).getTime());
    }
    return null;
  }

  /**
   * 获取某年月最后一天
   *
   * @param year 年
   * @param month 月
   * @return Date
   * @author xiaozhiwei date: 2019/1/16 16:25
   */
  public static Date getMonthLastDay(Integer year, Integer month) {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.YEAR, year);
    calendar.set(Calendar.MONTH, month - 1);
    calendar.set(Calendar.DAY_OF_MONTH, 1);
    calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
    calendar.set(Calendar.HOUR_OF_DAY, 23);
    calendar.set(Calendar.MINUTE, 59);
    calendar.set(Calendar.SECOND, 59);
    return calendar.getTime();
  }

  /**
   * 获取某年月第一天
   *
   * @param year 年
   * @param month 月
   * @return Date
   * @author xiaozhiwei date: 2019/1/16 16:25
   */
  public static Date getMonthStartDay(Integer year, Integer month) {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.YEAR, year);
    calendar.set(Calendar.MONTH, month - 1);
    calendar.set(Calendar.DAY_OF_MONTH, 1);
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    return calendar.getTime();
  }

  /**
   * 获取某年第一天
   *
   * @param year 年
   * @return Date
   * @author xiaozhiwei date: 2019/1/16 16:25
   */
  public static Date getYearStartDay(Integer year) {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.YEAR, year);
    calendar.set(Calendar.MONTH, 0);
    calendar.set(Calendar.DAY_OF_MONTH, 1);
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    return calendar.getTime();
  }


  /**
   * 获取某年最后一天
   *
   * @param year 年
   * @return Date
   * @author xiaozhiwei date: 2019/1/16 16:25
   */
  public static Date getYearEndDay(Integer year) {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.YEAR, year);
    calendar.set(Calendar.MONTH, 11);
    calendar.set(Calendar.DAY_OF_MONTH, 31);
    calendar.set(Calendar.HOUR_OF_DAY, 23);
    calendar.set(Calendar.MINUTE, 59);
    calendar.set(Calendar.SECOND, 59);
    return calendar.getTime();
  }

  /**
   * 获取当前时间的前一周
   *
   * @return java.util.Date
   * @author chengjin date: 2019/3/19 15:42
   */
  public static Timestamp getBeforeWeek() {
    Calendar c = Calendar.getInstance();
    c.setTime(new Date());
    c.add(Calendar.DATE, -6);
    c.set(Calendar.HOUR_OF_DAY, 0);
    c.set(Calendar.MINUTE, 0);
    c.set(Calendar.SECOND, 0);
    return new Timestamp(c.getTimeInMillis());
  }

  /**
   * 获取当前时间的前一年
   *
   * @return java.sql.Timestamp
   * @author chengjin date: 2019/3/19 19:16
   */
  public static Timestamp getBeforYear() {
    Calendar c = Calendar.getInstance();
    c.setTime(new Date());
    c.add(Calendar.YEAR, -1);
    return new Timestamp(c.getTimeInMillis());
  }

  /**
   * 计算时间差，返回n天n时n分n秒
   * @param start 开始时间
   * @param end 结束
   * @return String
   * @author whq
   * date 2019/6/14 14:41
   */
  public static String calcTime(Timestamp start,Timestamp end){
    if(start == null || end == null) {
      return "";
    }
    //时间差
    long l = end.getTime()-start.getTime();
    //天
    long day = l/(24*60*60*1000);
    //时
    long hour = (l/(60*60*1000)-day*24);
    //分
    long min = ((l/(60*1000))-day*24*60-hour*60);
    //秒
    long second = (l/1000-day*24*60*60-hour*60*60-min*60);

    StringBuffer str = new StringBuffer();
    if(day > 0){
      str.append(day).append("天");
    }
    if(hour > 0){
      str.append(hour).append("时");
    }
    if(min > 0){
      str.append(min).append("分");
    }
    if(second > 0){
      str.append(second).append("秒");
    }
    return str.toString();
  }

  /**
   * 获取当前毫秒
   * @return String
   */
  public static String getCurMSData(){
    SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSS");
    return df.format(new Date());
  }
}